﻿using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.IO;
using System.Text.RegularExpressions;
using Framework;

namespace FrameworkEditor
{
    public class OneToOneShare : IAbSetting
    {
        private Dictionary<string, List<string>> _refTab;
        private Regex _ignoreRegex;
        internal OneToOneShare(string path, string needRegexCfg, string ignoreRegexCfg) : base(path, needRegexCfg)
        {
            _refTab = new Dictionary<string, List<string>>();
            if (!string.IsNullOrEmpty(ignoreRegexCfg))
            {
                _ignoreRegex = new Regex(ignoreRegexCfg);
            }
        }

        internal override List<AssetBundleBuild> GetAllBuilders()
        {
            List<AssetBundleBuild> ret = new List<AssetBundleBuild>();
            if (string.IsNullOrEmpty(DirPath) || !Directory.Exists(DirPath))
            {
                Debug.LogWarning("OneToOneShare DirPath = " + DirPath + " does not exists!");
                return ret;
            }
            _refTab.Clear();
            List<AssetBundleBuild> rootBuilders = GetAllRefInfoAndRootBuilders();
            ret.AddRange(rootBuilders);

            foreach (var kvp in _refTab)
            {
                //如果某个资源被共用了,则独立构建为一个ab
                if (kvp.Value.Count > 1)
                {
                    ret.Add(new AssetBundleBuild()
                    {
                        assetBundleName = EditorUtils.GetRelativePathToDir(kvp.Key, EditorUtils.assetRootDir) + FrameworkSettings.AssetBundleExt,
                        assetNames = new string[] { kvp.Key },
                    });
                }
            }
            return ret;
        }

        /// <summary>
        /// 获取公用资源极其引用者情况log信息
        /// </summary>
        /// <returns>公用资源引用情况log</returns>
        public string GetBuilderSettingLog()
        {
            _refTab.Clear();
            List<AssetBundleBuild> rootBuilders = GetAllRefInfoAndRootBuilders();
            System.Text.StringBuilder logBuilder = new System.Text.StringBuilder();
            foreach (var kvp in _refTab)
            {
                logBuilder.AppendLine("公共资源: " + kvp.Key);
                foreach (var refers in kvp.Value)
                {
                    logBuilder.AppendLine("  引用者: " + refers);
                }
            }
            return logBuilder.ToString();
        }

        /// <summary>
        /// 获取根节点的构建设置、统计当前目录下的引用关系
        /// </summary>
        /// <returns></returns>
        private List<AssetBundleBuild> GetAllRefInfoAndRootBuilders()
        {
            List<AssetBundleBuild> rootBuilders = new List<AssetBundleBuild>();
            string[] files = Directory.GetFiles(DirPath, "*.*", SearchOption.AllDirectories);
            foreach (string file in files)
            {
                if (!IsNeedBuild(file))
                {
                    continue;
                }
                string assetPath = EditorUtils.GetPathRelativeToAssets(file);
                string[] allDeps = AssetDatabase.GetDependencies(assetPath);
                //Debug.Log("OneToOneShare.GetAllRefInfoAndRootBuilders  assetPath = " + assetPath + " allDeps[0] = " + allDeps[0]);
                foreach (string dep in allDeps)
                {
                    if (dep.Equals(assetPath))
                    {
                        continue;
                    }
                    if (dep.EndsWith(".prefab"))
                    {
                        Debug.LogError("prefab 之间的引用不是允许的,这里的prefab = " + assetPath + "引用了 " + dep);
                        continue;
                    }
                    if (null != _ignoreRegex && _ignoreRegex.IsMatch(dep))
                    {
                        continue;
                    }
                    if (!_refTab.ContainsKey(dep))
                    {
                        _refTab[dep] = new List<string>() { assetPath };
                    }
                    else
                    {
                        _refTab[dep].Add(assetPath);
                    }
                    //Debug.Log(" assetPath = " + assetPath + " dep = " + dep);
                }
                rootBuilders.Add(new AssetBundleBuild()
                {
                    assetBundleName = EditorUtils.GetRelativePathToDir(assetPath, EditorUtils.assetRootDir) + FrameworkSettings.AssetBundleExt,
                    assetNames = new string[] { assetPath },
                });
            }
            return rootBuilders;
        }
    }
}